package net.fruit.mq.client.trace.common;

import org.apache.rocketmq.common.message.MessageType;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class MQTraceDataEncoder {
    
    /**
     * 从轨迹数据字符串中解析出traceContext列表
     * 
     * @param traceData
     * @return
     */
    public static List<MQTraceContext> decoderFromTraceDataString(String traceData) {
        List<MQTraceContext> resList = new ArrayList<MQTraceContext>();
        if (traceData == null || traceData.length() <= 0) {
            return resList;
        }
        String[] contextList = traceData.split(String.valueOf(MQTraceConstants.FIELD_SPLITOR));
        for (String context : contextList) {
            String[] line = context.split(String.valueOf(MQTraceConstants.CONTENT_SPLITOR));
            if (line[0].equals(MQTraceType.Pub.name())) {
                MQTraceContext pubContext = new MQTraceContext();
                pubContext.setTraceType(MQTraceType.Pub);
                pubContext.setTimeStamp(Long.parseLong(line[1]));
                pubContext.setRegionId(line[2]);
                pubContext.setGroupName(line[3]);
                MQTraceBean bean = new MQTraceBean();
                bean.setTopic(line[4]);
                bean.setMsgId(line[5]);
                bean.setTags(line[6]);
                bean.setKeys(line[7]);
                bean.setStoreHost(line[8]);
                bean.setBodyLength(Integer.parseInt(line[9]));
                pubContext.setCostTime(Integer.parseInt(line[10]));
                bean.setMsgType(MessageType.values()[Integer.parseInt(line[11])]);
                // 兼容某个版本的snapshot，此处没有offsetid的情况
                if (line.length == 13) {
                    pubContext.setSuccess(Boolean.parseBoolean(line[12]));
                }
                else if (line.length == 14) {
                    bean.setOffsetMsgId(line[12]);
                    pubContext.setSuccess(Boolean.parseBoolean(line[13]));
                }
                pubContext.setTraceBeans(new ArrayList<MQTraceBean>(1));
                pubContext.getTraceBeans().add(bean);
                resList.add(pubContext);
            }
            else if (line[0].equals(MQTraceType.SubBefore.name())) {
                MQTraceContext subBeforeContext = new MQTraceContext();
                subBeforeContext.setTraceType(MQTraceType.SubBefore);
                subBeforeContext.setTimeStamp(Long.parseLong(line[1]));
                subBeforeContext.setRegionId(line[2]);
                subBeforeContext.setGroupName(line[3]);
                subBeforeContext.setRequestId(line[4]);
                MQTraceBean bean = new MQTraceBean();
                bean.setMsgId(line[5]);
                bean.setRetryTimes(Integer.parseInt(line[6]));
                bean.setKeys(line[7]);
                subBeforeContext.setTraceBeans(new ArrayList<MQTraceBean>(1));
                subBeforeContext.getTraceBeans().add(bean);
                resList.add(subBeforeContext);
            }
            else if (line[0].equals(MQTraceType.SubAfter.name())) {
                MQTraceContext subAfterContext = new MQTraceContext();
                subAfterContext.setTraceType(MQTraceType.SubAfter);
                subAfterContext.setRequestId(line[1]);
                MQTraceBean bean = new MQTraceBean();
                bean.setMsgId(line[2]);
                bean.setKeys(line[5]);
                subAfterContext.setTraceBeans(new ArrayList<MQTraceBean>(1));
                subAfterContext.getTraceBeans().add(bean);
                subAfterContext.setCostTime(Integer.parseInt(line[3]));
                subAfterContext.setSuccess(Boolean.parseBoolean(line[4]));
                if(line.length>=7){
                    // add the context type
                    subAfterContext.setContextCode(Integer.parseInt(line[6]));
                }
                resList.add(subAfterContext);
            }
        }
        return resList;
    }


    /**
     * 将轨迹上下文编码成轨迹数据字符串以及keyset集合
     * 
     * @param ctx
     * @return
     */
    public static MQTraceTransferBean encoderFromContextBean(MQTraceContext ctx) {
        if (ctx == null) {
            return null;
        }
        MQTraceTransferBean transferBean = new MQTraceTransferBean();
        StringBuilder sb = new StringBuilder(256);
        switch (ctx.getTraceType()) {
        case Pub: {
            MQTraceBean bean = ctx.getTraceBeans().get(0);
            sb.append(ctx.getTraceType()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(ctx.getTimeStamp()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(ctx.getRegionId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(ctx.getGroupName()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getTopic()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getMsgId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getTags()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getKeys()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getStoreHost()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getBodyLength()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(ctx.getCostTime()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getMsgType().ordinal()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(bean.getOffsetMsgId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                .append(ctx.isSuccess()).append(MQTraceConstants.FIELD_SPLITOR);
        }
            break;
        case SubBefore: {
            for (MQTraceBean bean : ctx.getTraceBeans()) {
                sb.append(ctx.getTraceType()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getTimeStamp()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getRegionId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getGroupName()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getRequestId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(bean.getMsgId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(bean.getRetryTimes()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(bean.getKeys()).append(MQTraceConstants.FIELD_SPLITOR);//
            }
        }
            break;
        case SubAfter: {
            for (MQTraceBean bean : ctx.getTraceBeans()) {
                sb.append(ctx.getTraceType()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    // .append(ctx.getTimeStamp()).append(OnsTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getRequestId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(bean.getMsgId()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getCostTime()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.isSuccess()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(bean.getKeys()).append(MQTraceConstants.CONTENT_SPLITOR)//
                    .append(ctx.getContextCode()).append(MQTraceConstants.FIELD_SPLITOR);
            }
        }
            break;
        default:
        }
        transferBean.setTransData(sb.toString());
        for (MQTraceBean bean : ctx.getTraceBeans()) {
            transferBean.getTransKey().add(bean.getMsgId());
            if (bean.getKeys() != null && bean.getKeys().length() > 0) {
                transferBean.getTransKey().add(bean.getKeys());
            }
        }
        return transferBean;
    }
}
